/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gfdclient;

import java.io.File;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.util.Vector;
import networkservice.PingNetService;
import userservercontroller.IUserServerController;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import userservercontroller.IAutorizationClient;
import userservercontroller.WrongKeyExeption;
/**
 * @author Aleksey ID = 2001
 * @author Truewar Ashman (<a href="mailto:truewar@hotmail.ru">truewar@hotmail.ru</a>) ID = 2009
 * @version 0.2
 * v0.1 (Aleksey) ---
 * v0.2 (TrueWar) Methods to add/delete/read last user information from settings file.
*/
public class InnerLogic {
    /** адрес сервера арбитра*/
    private String arbitrUSCStubAddress = "rmi://localhost/USCProxy";
    /** адрес сервера кандидата*/
    private String candidateUSCStubAddress = null;
    /** ссылка на управляющий класс */
    private IUserServerController USC = null;
    /** авторизационный ключ */
    private long autorizationKey=-1;
    /** Список загруженных файлов */
    private Vector<File> files = new Vector<File>();
    /** сервис сетевого соединения */
    private PingNetService pingNetService;
    /** Ссылка на главное окно клиента */
    private MainFrame frame;
    /** Логин */
    private String login="";
    /** Пароль */
    private String password="";
	/** Путь к файлу с настройками */
	public String settingsFileName;


    public InnerLogic(MainFrame pFrame) {
        frame = pFrame;
        pingNetService = new PingNetService(this);
		settingsFileName = "settings.ini";
    }

    /**
     * Получить какой то список файлов
     * @return какой то список файлов
     */
    public Vector<File> getFiles() {
        return files;
    }

    /**
     * Получить ссылку на главное окно клиента
     * @return ссылка на MainFrame
     */
    public MainFrame getMainFrame()
    {
        return frame;
    }

    /**
     * Инициализировать сеть
     * при успешной инициализации устанавливает адрес кандидата
     * @param  stubAddress - адрес удалённого объекта на сервере
     * @return объект управления сервером
     */
    public IUserServerController connectServer(String stubAddress)
            throws RemoteException, NotBoundException, MalformedURLException{
        disconnectServer();
        //Устанавливаем диспетчер защиты RMI
        System.setProperty("java.security.policy", "client.policy");
        RMISecurityManager manager = new RMISecurityManager();
        System.setSecurityManager(manager);
        //получить ссылку на управляющий класс
        USC = (IUserServerController) Naming.lookup(stubAddress);
        arbitrUSCStubAddress = stubAddress;
        // если соединение установлено зпросить кандидата
        if (USC != null){ candidateUSCStubAddress = USC.getCandidateIP(); }
        return USC;
    }

    /**
     * переподключиться к последнему серверу
     * @return объект управления сервером
     */
    public IUserServerController reconnectServer()
            throws RemoteException, NotBoundException, MalformedURLException{
        return connectServer(arbitrUSCStubAddress);
    }

    /**
     * Разорвать соединение
     */
    public void disconnectServer (){
        pingNetService.stopPing();
        USC = null;
    }

    /**
     * Принудительно разорвать соединение
     */
    public void killConnection(){
      frame.setConnectStatus(false); //изменить картинку соединения
      disconnectServer();
    }

    /**
     * Напечатать сообщение в журнал пользователя
     * @param msg - сообщение
     */
    public void printMsg(String msg){
     frame.setStatusBarText(msg);
     frame.msg("Отключение от сервера завершилось успешно");
    }

    /**
     * Попытаться авторизоваться на сервере.
     * Запоминает логин, пароль, авторизационный ключ и в случае успешной
     * авторизации запускает пинг сервера
     * @param login логин
     * @param password пароль
     * @return авторизационный ключ
     * @throws java.rmi.RemoteException ошибка соединения
     */
    public long autorization(String login,String password)throws RemoteException{
        if(USC==null) throw new RemoteException("Connection doesn't set");
        if(autorizationKey>=0) USC.logoff(autorizationKey);
        //попробовать авторизоваться
        this.login=login;
        this.password=password;
        autorizationKey=USC.tryAuthorization(login, password);
        if(autorizationKey>=0) {
            pingNetService.startPing();
            //Запрос файлов репозитория (ТЕСТОВАЯ)
            files.clear();
            try {
                Vector<String> fileNames=USC.getFiles(autorizationKey, "");
                if(fileNames!=null)
                    for(String fn:fileNames){
                        files.add(new File(fn));
                        System.out.println("loaded file "+ fn);
                    }
                frame.updateFileList();

                //MainFrame.

            }catch (WrongKeyExeption ex) { }
        }
        return autorizationKey;
    }

    /**
     * Попытаться переавторизоваться на сервере.
     * Метод будет работать корректно только в случае если авторизация
     * производилась через метод autorization класса InnerLogic
     * @return авторизационный ключ
     * @throws java.rmi.RemoteException ошибка соединения
     */
    public long reautorization() throws RemoteException{
        if(USC==null) throw new RemoteException("Connection doesn't set");
        //проверить текущий статус авторизации
        if (USC.pingLastOperationStatus(autorizationKey)!=-1)
            return autorizationKey;
        //попробовать авторизоваться
        autorizationKey=USC.tryAuthorization(login, password);
        if(autorizationKey>=0) pingNetService.startPing();
        return autorizationKey;
    }

    /**
     * Возвращается адресс КУСа, йоу!
     * @return rmi://[IP-адрес | доменное имя ]/[имя прокси-объекта]
     */
    public String getUSCAddress() {  return arbitrUSCStubAddress; }

    /**
     * Запросить кандидата
     * @return адрес кандидата
     */
    public String getCandidateAddress(){ return candidateUSCStubAddress;}

    /**
     * Установить сервер-кандидат
     * @param address адес сервера кандидата
     */
    public void setCandidateAddress(String address){
        candidateUSCStubAddress=address;
    }

    /**
     * Запросить ссылку на управляющий класс
     * @return ссылка на управляющий класс
     */
    public IUserServerController getUSC(){return USC;}

    /**
     * Установить авторизационный ключ
     * @param key авторизационный ключ
     */
    public void setAutorizationKey(long key){autorizationKey=key;}
    
    /**
     * Запросить авторизационный ключ
     * @return авторизационный ключ
     */
    public long getAutorizationKey(){return autorizationKey;}
 
    /**
     * Начать ping сервера
     * @return true - в случае открытого соединения, иначе false
     */
    public boolean startPing(){
        if (USC != null) { pingNetService.startPing(); return true;}
        else return false;
    }

	/**
	 * It return username, who has logined last time
	 * @return name of user or null, if there were errors.
	 */
	public String getLastLogined()
	{
		try
		{
			return this.frame.encoding.set.getField("login");
		} catch(Exception ex){}
		return null;
	}

	/**
	 * It return last accessed server.
	 * @return last accessed server or null, if there were errors.
	 */
	public String getLastServerLogined()
	{
		try
		{
			return this.frame.encoding.set.getField("server");
		} catch(Exception ex){}
		return null;
	}

	/**
	 * It writes last username into settings file.
	 * @param name username
	 * @param server name of last accessed server
	 */
	public void setLastLogined(String name, String server)
	{
		this.frame.encoding.set.addField("login", name);
		this.frame.encoding.set.addField("server", server);
	}

}